package comparisons

import (
	"jvm/nzpJvm/instructions/base"
	"jvm/nzpJvm/runtime_area"
)

// 弹出栈顶两个int变量并且进行比较
// 两个int值相等则跳转
type IF_ICMPEQ struct{ base.BranchInstruction }
// 两个int值不相等则跳转
type IF_ICMPNE struct{ base.BranchInstruction }
// 小于
type IF_ICMPLT struct{ base.BranchInstruction }
// 小于等于
type IF_ICMPLE struct{ base.BranchInstruction }
// 大于
type IF_ICMPGT struct{ base.BranchInstruction }
// 大于等于
type IF_ICMPGE struct{ base.BranchInstruction }

func (self *IF_ICMPEQ) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// 后push进去的数会先弹出
	popBack := stack.PopInt()
	// 先push进去的数会后弹出
	// 例如java代码 a > b，操作数入栈时是a先入栈，b后入栈。
	// 然后到这个比较指令进行比较时，是b先出栈，a后出栈，下面的opoBack变量获取到的值是b，popPre获取到的值是a
	popPre := stack.PopInt()
	if popBack == popPre {
		base.Branch(frame, self.Offset)
	}
}

func (self *IF_ICMPNE) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// 后push进去的数会先弹出
	// 先push进去的数会后弹出
	// 例如java代码 a > b，操作数入栈时是a先入栈，b后入栈。
	// 然后到这个比较指令进行比较时，是b先出栈，a后出栈，下面的opoBack变量获取到的值是b，popPre获取到的值是a
	popBack := stack.PopInt()
	popPre := stack.PopInt()
	if popBack != popPre {
		base.Branch(frame, self.Offset)
	}
}

func (self *IF_ICMPLT) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// 后push进去的数会先弹出
	// 先push进去的数会后弹出
	// 例如java代码 a > b，操作数入栈时是a先入栈，b后入栈。
	// 然后到这个比较指令进行比较时，是b先出栈，a后出栈，下面的opoBack变量获取到的值是b，popPre获取到的值是a
	popBack := stack.PopInt()
	popPre := stack.PopInt()
	if popPre < popBack {
		base.Branch(frame, self.Offset)
	}
}

func (self *IF_ICMPLE) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// 后push进去的数会先弹出
	// 先push进去的数会后弹出
	// 例如java代码 a > b，操作数入栈时是a先入栈，b后入栈。
	// 然后到这个比较指令进行比较时，是b先出栈，a后出栈，下面的opoBack变量获取到的值是b，popPre获取到的值是a
	popBack := stack.PopInt()
	popPre := stack.PopInt()
	if popPre <= popBack {
		base.Branch(frame, self.Offset)
	}
}
// 如果先push进去的那个数大于后push进去的那个数，则跳转
func (self *IF_ICMPGT) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// 后push进去的数会先弹出
	// 先push进去的数会后弹出
	// 例如java代码 a > b，操作数入栈时是a先入栈，b后入栈。
	// 然后到这个比较指令进行比较时，是b先出栈，a后出栈，下面的opoBack变量获取到的值是b，popPre获取到的值是a
	popBack := stack.PopInt()
	popPre := stack.PopInt()
	if popPre > popBack {
		base.Branch(frame, self.Offset)
	}
}

func (self *IF_ICMPGE) Execute(frame *runtime_area.Frame) {
	stack := frame.OperandStack()
	// 后push进去的数会先弹出
	// 先push进去的数会后弹出
	// 例如java代码 a > b，操作数入栈时是a先入栈，b后入栈。
	// 然后到这个比较指令进行比较时，是b先出栈，a后出栈，下面的opoBack变量获取到的值是b，popPre获取到的值是a
	popBack := stack.PopInt()
	popPre := stack.PopInt()
	if popPre >= popBack {
		base.Branch(frame, self.Offset)
	}
}
